package com.heima.comment.service.impl;

import com.heima.api.schedule.WemediaFeign;
import com.heima.api.user.IUserClient;
import com.heima.comment.pojos.CommentRepay;
import com.heima.comment.pojos.LikeRecord;
import com.heima.comment.service.ICommentService;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.exception.CustomException;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.comment.pojos.CommentSave;
import com.heima.model.comment.vos.CommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.SensitiveDto;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.utils.common.UserThreadLocal;
import com.heima.utils.common.WmThreadLocalUtil;
import com.mongodb.client.model.Filters;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @AuthOr: Anna Zhang
 * @Date:2024/8/21-23:34
 * @ClassName:com.heima.comment.service.impl
 * @Description:
 **/
@Service
@Slf4j
@RequiredArgsConstructor
public class CommentServiceImpl implements ICommentService {

    private final MongoTemplate mongoTemplate;
    private final WemediaFeign wemediaFeign;
    private final IUserClient userClient;
    private final StringRedisTemplate redisTemplate;
    private final static String SAVE_COMMENT = "SAVE_COMMENT";
    private final static String LIKE_COMMENT = "LIKE_COMMENT";


    /**
     * 保存评论
     * @param saveDto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto saveDto) {
        Boolean mi = redisTemplate.opsForValue().setIfAbsent
                (SAVE_COMMENT + UserThreadLocal.get(), "1", 1, TimeUnit.SECONDS);
        if(!mi){
            throw new CustomException(AppHttpCodeEnum.NOT_REPETITION_OPERATION);
        }
        String content = saveDto.getContent();
        if(content.length()>140){
            throw new CustomException(AppHttpCodeEnum.ARTICLEID_IS_EMPTY);
        }
        //评论内容做垃圾检测
        Boolean flag =  checkComment(content);
        if(!flag){
            throw new CustomException(AppHttpCodeEnum.EXIST_SENSITIVE_WORDS);
        }
        //检测通过 存入mangodb
        CommentSave comment = new CommentSave();
        comment.setAuthorId(UserThreadLocal.get());
        String username = userClient.getUser(UserThreadLocal.get());
        comment.setAuthorName(username);
        comment.setLikes(0);
        comment.setReply(0);
        comment.setCreatedTime(new Date());
        comment.setEntryId(saveDto.getArticleId());
        comment.setContent(saveDto.getContent());
        mongoTemplate.save(comment);
        return new ResponseResult(200,"评论成功",comment,null);
    }

    /**
     * 检测评论内容是否合规
     * @param content
     * @return
     */
    private Boolean checkComment(String content) {
        Map<String, Integer> matchResult = SensitiveWordUtil.matchWords(content);
        if(!CollectionUtils.isEmpty(matchResult)){
            log.info("存在敏感词");
            return false;
        }
        return true;
    }

    @PostConstruct
    private void init(){
        List<String> allSensitive = wemediaFeign.selectAllSensitive(new SensitiveDto());
        SensitiveWordUtil.initMap(allSensitive);
    }


    /**
     * 加载评论列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult loadComment(CommentDto dto) {
        Long articleId = dto.getArticleId();
        Query query = new Query().addCriteria(Criteria.where("entryId").is(articleId))
                .addCriteria(Criteria.where("createdTime").lt(dto.getMinDate()))
                .with(Sort.by(Sort.Direction.DESC, "createdTime"));
        List<CommentSave> commentList = mongoTemplate.find(query,CommentSave.class);
        Query query1 = new Query().addCriteria(Criteria.where("authorId").is(UserThreadLocal.get()));
        List<LikeRecord> likeRecordList = mongoTemplate.find(query1, LikeRecord.class);
        Map<String, Integer> commentIdMap = likeRecordList.stream().collect(Collectors.toMap(
                LikeRecord::getCommentId, likeRecord -> 1
        ));
        List<CommentVo> collect = commentList.stream().map(one -> {
            CommentVo commentVo = new CommentVo();
            BeanUtils.copyProperties(one, commentVo);
            if(commentIdMap.get(one.getId()) != null){
                commentVo.setOperation((short) 0);
            }
            return commentVo;
        }).collect(Collectors.toList());

        return new ResponseResult(AppHttpCodeEnum.SUCCESS.getCode(),"查询成功",collect,null);
    }

    /**
     * 点赞
     * @param likeDto
     * @return
     */
    @Override
    public ResponseResult likeComment(CommentLikeDto likeDto) {
        //获取redis操作对象
        ValueOperations<String, String> operation = redisTemplate.opsForValue();
        //利用redis单线程特性和setIfAbsent方法的特性 根据其返回值判断是否往后执行
        Boolean mi = operation.setIfAbsent(LIKE_COMMENT + UserThreadLocal.get()
                , "1", 1, TimeUnit.SECONDS);
        if(!mi){
            throw new CustomException(AppHttpCodeEnum.NOT_REPETITION_OPERATION);
        }
        //根据id查询到那条评论
        CommentSave comment = mongoTemplate.findById(likeDto.getCommentId(), CommentSave.class);
        if(comment==null){
            throw new CustomException(AppHttpCodeEnum.REMARK_NOT_EXIST);
        }
        //判断类型 更新其likes字段
        Integer oldLikesNum = comment.getLikes();
        if(likeDto.getOperation()==0){
            //点赞
            comment.setLikes(oldLikesNum+1);
            mongoTemplate.save(comment);
            //添加点赞的一行记录
            saveLikeRecord(comment);
        }else{
            //取消点赞
            comment.setLikes(oldLikesNum-1);
            mongoTemplate.save(comment);
            removeLikeRecord(comment);
        }
        HashMap<String, Object> res = new HashMap<>();
        res.put("likes",comment.getLikes());
        return new ResponseResult(AppHttpCodeEnum.SUCCESS.getCode(),"查询成功",res,null);
    }

    /**
     * 移除点赞记录
     * @param comment
     */
    private void removeLikeRecord(CommentSave comment) {

        Query query = new Query().addCriteria(Criteria.where("CommentId").is(comment.getId()));
        mongoTemplate.remove(query,LikeRecord.class);
    }

    /**
     * 新增点赞记录
     * @param comment
     */
    private void saveLikeRecord(CommentSave comment) {
        LikeRecord record = new LikeRecord();
        record.setCommentId(comment.getId());
        record.setType(0);
        record.setAuthorId(UserThreadLocal.get());
        record.setCreatedTime(new Date());
        mongoTemplate.save(record);
    }
}
